App.require(function () {
    var app = App.getCurrent();

    app.defineComponent("str-text", {
        set value(val) {
            if (val) this.domList.textField.classList.add("str-text-edit");
            else this.domList.textField.classList.remove("str-text-edit");
            this.domList.input.value = val;
        },
        get value() {
            return this.domList.input.value;
        },
        set placeholder(value) {
            if (this.property.placeholder === value) return ;
            this.property.placeholder = value;
            this.domList.input.placeholder = value;
        },
        get placeholder() {
            return this.property.placeholder;
        },
        set form(value) {
            if (this.property.form === value) return;
            this.domList.input.form = value;
        },
        get form() {
            return this.property.form;
        },
        set rendertype(value) {
            var property = this.property;
            if (property.rendertype === value) return;
            var textField = this.domList.textField, input = this.domList.input;
            textField.setAttribute("rendertype", value);
            property.rendertype = value;
            if (property.size === "small" && property.rendertype === "filled") {
                input.placeholder= property.label;
            }
        },
        get rendertype() {
            return this.property.rendertype;
        },
        get type() {
            return this.domList.input.type;
        },
        set type(value) {
            var type = {
                text: "text",
                email: "email",
                tel: "tel",
                url: "url",
                password: "password",
                search: "search",
                number: "number"
            }[value] || "text";
            this.domList.input.type = type;
            this.property.type = type;
        },
        set label(value) {
            var property = this.property;
            property.label = value;
            if (property.size === "small" && property.rendertype === "filled") {
                this.domList.input.placeholder= value;
            }
            this.domList.textField.firstElementChild.textContent = value;
        },
        get label() {
            return this.property.label;
        },
        set counter(val) {
            val = parseInt(val);
            if (this.property.counter === val) return;
            var oldCounter = this.property.counter, container = this.domList.helpContainer, input = this.domList.input;
            if (!oldCounter) {
                var div = document.createElement("div");
                div.className = "text-counter";
                div.textContent = input.value.length + " / " + val;
                container.appendChild(div);
            }
            else {
                container.lastElementChild.textContent = input.value.length + " / " + val;
            }
            input.maxLength = val;
            this.property.counter = val;
        },
        get counter() {
            return this.property.counter;
        },
        set leadicon(val) {
            if (val === this.property.leadicon) return;
            var property = this.property, oldIcon = property.leadicon;
            this.domList.textField.setAttribute("leadicon", val);
            if (oldIcon) {
                var component = this.getComponentById("lead");
                if (val) component.icon = val;
                else {
                    this.removeComponent(component);
                    this.domList.textField.removeAttribute("leadicon");
                }
            }
            else {
                this.insertAdjacentHTML(this.domList.ripple, '<str-icon id="lead" class="leadicon" icon="' + val + '" width="24" height="24" nofocus></str-icon>', "afterend");
            }
            property.leadicon = val;
        },
        get leadicon() {
            return this.property.leadicon;
        },
        set trailicon(val) {
            if (val === this.property.trailicon) return;
            this.domList.textField.setAttribute("trailicon", val);
            var property = this.property, oldIcon = property.trailicon;
            if (oldIcon) {
                var component = this.getComponentById("trail");
                if (val) component.icon = val;
                else {
                    this.removeComponent(component);
                    this.domList.textField.removeAttribute("trailicon");
                }
            }
            else {
                this.insertAdjacentHTML(this.domList.textField, '<str-icon id="trail" class="trailicon" icon="' + val + '" width="24" height="24" nofocus></str-icon>', "beforeend");
            }
            property.trailicon = val;
        },
        get trailicon() {
            return this.property.trailicon;
        },
        get assistivetype() {
            return this.property.assistivetype;
        },
        get assistivetext() {
            return this.property.assistivetext;
        },
        set assistive(obj) {
            var property = this.property, oldType = property.assistivetype, textField = this.domList.textField;
            var container = this.domList.helpContainer;
            if (!obj.type) {
                if (oldType) {
                    container.removeChild(container.firstElementChild);
                    textField.classList.remove("str-text-error");
                }
                property.assistivetext = obj.text;
                property.assistivetype = obj.type;
                return;
            }
            if (!oldType) {
                var div = document.createElement("div");
                div.className = "addtion-" + obj.type;
                div.textContent = obj.text;
                container.insertBefore(div, container.firstElementChild);
            }
            else {
                var target = container.firstElementChild;
                if (oldType !== obj.type) {
                    target.className =" addtion-" + obj.type;
                    textField.setAttribute("assisitivetext", obj.type);
                }
                target.textContent = obj.text;
            }
            property.assistivetext = obj.text;
            property.assistivetype = obj.type;
        },
        get assistive() {
            var property = this.property;
            return {
                type: property.assistivetype,
                text: property.assistivetext
            }
        },
        get size() {
            return this.property.size;
        },
        set size(value) {
            if (this.property.size === value) return;
            this.domList.textField.setAttribute("size", value);
            this.property.size = value;
        },
        get name() {
            return this.property.name;
        },
        set name(val) {
            if (this.property.name === val) return;
            var input = this.domList.input, label = this.domList.label;
            input.name = val;
            input.id = val;
            label.htmlFor = val;
            this.property.name = val;
        },
        set pattern(val) {
            if (this.property.pattern === val) return;
            this.domList.input.pattern = val;
            this.property.pattern = val;
        },
        get pattern() {
            return this.property.pattern;
        },
        get disabled() {
            return this.property.disabled;
        },
        set disabled(value) {
            value = value ? "disabled" : "";
            if (this.property.disabled === value) return;
            var classList = this.domList.textField.classList; 
            if (value) {
                this.domList.input.setAttribute("disabled", "");
                this.property.disabled = "disabled";
                classList.add("str-text-field-disabled");
            }
            else {
                this.domList.input.removeAttribute("disabled");
                this.property.disabled = "";
                classList.add("str-text-field-disabled");
            }
        },
        get required() {
            return this.property.required;
        },
        set required(value) {
            value = value ? "required" : "";
            if (this.property.required === value) return;
            
            if (value) {
                this.domList.input.setAttribute("required", "");
                this.property.required = "required";
            }
            else {
                this.domList.input.removeAttribute("required");
                this.property.required = "";
            }
        },
        get readonly() {
            return this.property.readonly;
        },
        set readonly(value) {
            value = value ? "readonly" : "";
            if (this.property.readonly === value) return;
            var classList = this.domList.textField.classList; 
            if (value) {
                this.domList.input.setAttribute("readonly", "");
                this.property.readonly = "readonly";
                classList.add("str-text-field-readonly");
            }
            else {
                this.domList.input.removeAttribute("readonly");
                this.property.readonly = "";
                classList.remove("str-text-field-readonly");
            }
        },
        get autofocus() {
            return this.property.autofocus;
        },
        get autocomplete() {
            return this.property.autocomplete;
        },
        set min(value) {
            if (this.property.type === "number") {
                this.domList.input.min = parseFloat(value);
            }
        },
        get min() {
            if (this.property.type === "number") {
                return this.property.min;
            }
            return undefined;
        },
        set max(value) {
            if (this.property.type === "number") {
                this.domList.input.max = parseFloat(value);
            }
        },
        get max() {
            if (this.property.type === "number") {
                return this.property.max;
            }
            return undefined;
        },
        set step(value) {
            if (this.property.type === "number") {
                this.domList.input.step = parseFloat(value);
            }
        },
        get step() {
            if (this.property.type === "number") {
                return this.property.step;
            }
            return undefined;
        },
        get className() {
            return this.property.class;
        },
        set className(value) {
            if (this.property.class === value) return;
            this.domList.container.className = value;
            this.property.class = value;
        },
        get defaultValue() {
            return this.domList.input.defaultValue;
        },
        getDomObj: function () {
            this.attachDom("input", "input")
                .attachDom("label", "label")
                .attachDom('[role="formitemcontainer"]', "container")
                .attachDom('[role="formitem"]', "textField")
                .attachDom(".ripple-line", "ripple")
                .attachDom(".str-text-help-container", "helpContainer")
                .attachEvent("input", "invalid", this.invalidHandler, false)
                .attachEvent("input", "keyup", this.keyupHandler, false)
                .attachEvent("input", "keypress", this.keypressHandler, false)
                .attachEvent("input", "focus", this.focusHandler, false)
                .attachEvent("input", "input", this.inputHandler, false)
                .attachEvent("input", "change", this.changeHandler, false)
                .attachEvent("input", "keydown", this.keydownHandler, false)
                .attachEvent("input", "blur", this.blurHandler, false);
        },
        invalidHandler: function (ev) {
            this.dispatchCustomEvent("textinvalid", { event: ev, component: this, target: ev.currentTarget });
        },
        keypressHandler: function (ev) {
            this.dispatchCustomEvent("textkeypress", { event: ev, component: this, target: ev.currentTarget });
        },
        keyupHandler: function (ev) {
            this.dispatchCustomEvent("textkeyup", { event: ev, component: this, target: ev.currentTarget });
        },
        keydownHandler: function (ev) {
            var count = this.property.counter;
            this.dispatchCustomEvent("textkeydown", { event: ev, component: this, target: ev.currentTarget });
            if (count >= ev.currentTarget.value.length && this.property.type === "number" && ev.key.toLowerCase() === "e") {
                ev.preventDefault();
            }
        },
        inputHandler: function (ev) {
            var target = ev.target;
            this.updateCounter(target.value.length);
            this.dispatchCustomEvent("textinput", { event: ev, component: this, target: ev.currentTarget });
        },
        changeHandler: function (ev) {
            this.dispatchCustomEvent("textchange", { event: ev, component: this, target: ev.currentTarget });
        },
        focusHandler: function (ev) {
            var target = ev.target;
            this.setEdit(target);
            this.dispatchCustomEvent("textfocus", { target: target, component: this, event: ev });
        },
        setEdit: function (target, isCantCancel) {
            target = target || this.domList.input;
            target.parentNode.classList.add("str-text-edit");
            target.parentNode.classList.add("str-text-color");
            if (isCantCancel) this.data.cantCancel = true;
        },
        get validate () {
            return this.domList.input.validate;
        },
        removeEdit: function (target, isRemove) {
            if (isRemove) this.data.cantCancel = false;
            target = target || this.domList.input;
            if (!target.value) {
                if (!this.data.cantCancel) target.parentNode.classList.remove("str-text-edit");
            }
            if (!this.data.cantCancel)  target.parentNode.classList.remove("str-text-color");
        },
        blurHandler: function (ev) {
            var target = ev.target;
            this.removeEdit(target);
            this.dispatchCustomEvent("textblur", { event: ev, target: target, component: this });
        },
        updateCounter: function (len) {
            var counter = this.property.counter;
            if (counter) {
                this.domList.helpContainer.lastElementChild.textContent = [len, "/", counter].join(" ");
            }
        },
        render: function (next) {
            this.computeData();
            this.fetch("index.html", function (text) {
                return next(this.renderHTML(text));
            });
        },
        computeData: function () {
            var property = this.property;
            property.rendertype = property.rendertype || "filled";
            property.size = property.size || "normal";
            property.type = property.type || "text";
            property.name = property.name || this.uid;
            property.label = property.label || property.name;
            property.value = property.value || "";
            property.class = property.class || "";
            property.form = property.form || "";
            property.pattern = property.pattern || "";
            property.placeholder = property.placeholder || "";
            if (property.size === "small" && property.rendertype === "filled") property.placeholder = property.label || property.placeholder;
            if (property.counter) property.counter = parseInt(property.counter);
            property.autocomplete = property.autocomplete || "";
            property.required = typeof property.required !== "undefined" ? "required" : "";
            property.readonly = typeof property.readonly !== "undefined" ? "readonly" : "";
            property.disabled = typeof property.disabled !== "undefined" ? "disabled" : "";
            property.autofocus = typeof property.autofocus !== "undefined" ? "autofocus" : "";
            property.hiddenbottom = typeof property.hiddenbottom !== "undefined" ? "hiddenbottom" : "";
            if (property.type === "number") {
                property.min = typeof property.min !== undefined ? parseFloat(property.min) : "";
                property.max = typeof property.max !== undefined ? parseFloat(property.max) : "";
                property.step = typeof property.step !== undefined ? parseFloat(property.step) : "";
            }
            this.data.itemrendertype = this.createPropertyStr({
                rendertype: property.rendertype,
                size: property.size,
                leadicon: property.leadicon,
                trailicon: property.trailicon,
                class: this.createClass(),
                assistivetype: property.assistivetype
            });
            this.createInputAddtionAttribute(property);
        },
        get hiddenbottom() {
            return this.property.hiddenbottom;
        },
        set hiddenbottom(value) {
            value = value ? "hiddenbottom" : "";
            if (value === this.property.hiddenbottom) return;
            var classList = this.domList.helpContainer.classList;
            if (value) {
                classList.add(value);
            }
            else {
                classList.remove(value);
            }
            this.property.hiddenbottom = value;
        },
        createInputAddtionAttribute(property) {
            var result = [];
            if (property.counter) result.push("maxlength='" + property.counter + "'");
            if (property.required) result.push("required");
            if (property.disabled) result.push("disabled");
            if (property.readonly) result.push("readonly");
            if (property.autofocus) result.push("autofocus");
            if (property.form) result.push("form='" + property.form + "'");
            if (property.placeholder) result.push("placeholder='" + property.placeholder + "'");
            if (property.pattern) result.push("pattern='" + property.pattern + "'");
            if (property.value) result.push("value='" + property.value + "'");
            if (property.autocomplete) result.push("autocomplete='" + property.autocomplete + "'");
            if (property.type === "number") {
                if (typeof property.min !== "string") result.push("min='" + property.min + "'");
                if (typeof property.max !== "string") result.push("max='" + property.max + "'");
                if (typeof property.step !== "string") result.push("step='" + property.step + "'");
            }
            var dataset = this.dataset;
            for (var key in dataset) {
                result.push("data-" + key + "=" + dataset[key]);
            }
            this.data.addtionattribute = result.join(" ");
        },
        createClass: function () {
            var property = this.property, 
                classList = [],
                value = property.value;
            
            if (value) classList.push("str-text-edit");
            if (property.disabled) classList.push("str-text-field-disabled");
            if (property.readonly) classList.push("str-text-field-readonly");

            return classList.join(" ");
        },
        init: function () {
            var property = this.property;
            if (property.assistivetype == "error") {
                this.domList.input.setCustomValidity(property.assistivetext);
            }
        },
        focus: function () {
            var input = this.domList.input;
            input.focus();
            this.setEdit(input);
        },
        blur: function () {
            var input = this.domList.input;
            input.blur();
            this.removeEdit(input);
        },
        select: function () {
            this.domList.input.select();
        },
        setSelectionRange: function (start, end) {
            this.domList.input.setSelectionRange(start, end);
        },
        checkValidity: function () {
            return this.domList.input.checkValidity();
        },
        reset: function () {
            var input = this.domList.input;
            input.value = input.defaultValue;
            this.property.value = input.defaultValue;
            if (input.value) this.domList.textField.classList.remove("str-text-edit");
        },
        stepDown: function () {
            if (this.property.type === "number") {
                this.domList.input.stepDown();
            }
        },
        stepUp: function () {
            if (this.property.type === "number") {
                this.domList.input.stepUp();
            }
        },
        setCustomValidity: function (str) {
            this.domList.input.setCustomValidity(str);
        }
    });
});